/**********************************************************************************
Copyright (C), by AppleCai
Project                      : Study Kernel
Description                  : BSP level for MPU6500
CPU and Compiler             : AM335x,ARM-LINIX-GCC
|----------------------------------------------------------------------------------
|               R E V I S I O N   H I S T O R Y
|----------------------------------------------------------------------------------
| Date        Version  Author   Description
| --------    -------  ------   ---------------------------------------------------
| 2020-12-14  1.0.0    AppleCai MPU6500_001: Initial release version
**********************************************************************************/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/input-polldev.h>
#include <linux/of_device.h>
#include "apple6500.h"
#if 0  //dts
&i2c2 {  
	pinctrl-names = "default";
	pinctrl-0 = <&i2c2_pins>;

	status = "okay";
	clock-frequency = <100000>;

	apple_MPU6500: apple_MPU6500@68 {
		compatible ="applecai,apple6500i2c";
		reg = <0x68>;
	};
};
#endif
static int apple6500_read_i2c(struct device *dev, unsigned off)
{
	struct i2c_client *c = to_i2c_client(dev);
	int ret;

	ret = i2c_smbus_read_byte_data(c, off);
	if (ret < 0)
		dev_err(dev,"failed to read register 0x%02x, error %d\n",off, ret);

	return ret;
}

static int apple6500_write_i2c(struct device *dev, unsigned off, unsigned char v)
{
	struct i2c_client *c = to_i2c_client(dev);
	int error;

	error = i2c_smbus_write_byte_data(c, off, v);
	if (error < 0) {
		dev_err(dev,"failed to write to register 0x%02x, error %d\n",off, error);
		return error;
	}

	return 0;
}

static int apple6500_read_block_i2c(struct device *dev, unsigned off,unsigned char *buf, size_t size)
{
	struct i2c_client *c = to_i2c_client(dev);
	int err;

	err = i2c_smbus_read_i2c_block_data(c, off, size, buf);
	if (err < 0) {
		dev_err(&c->dev,"failed to read block data error %d\n", err);
		return err;
	}

	return 0;
}
static const struct apple6500_transfer_func apple6500_tf_i2c = {
	.write = apple6500_write_i2c,
	.read = apple6500_read_i2c,
	.readblock = apple6500_read_block_i2c
};

static const struct of_device_id apple6500_dt_ids[] = {
	{ .compatible = "applecai,apple6500i2c"},
	{ /* sentinel */ }
};
/*
 * I2C probe
 */
static int apple6500_i2c_probe(struct i2c_client *c,
			 const struct i2c_device_id *id)
{
	struct apple6500 *m;
	int err;
	/* Check basic functionality */
	err = i2c_check_functionality(c->adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA|
								  I2C_FUNC_SMBUS_READ_BYTE_DATA|
								  I2C_FUNC_SMBUS_READ_I2C_BLOCK);
	if (!err) {
		dev_err(&c->dev, "%s adapter not supported\n",
			dev_driver_string(&c->adapter->dev));
		return -ENODEV;
	}
	m = apple6500_probe(&c->dev,&apple6500_tf_i2c);
	if (IS_ERR(m))
		return PTR_ERR(m);
	i2c_set_clientdata(c, m);

	return 0;
}

static int apple6500_i2c_remove(struct i2c_client *c)
{
	struct apple6500 *m = i2c_get_clientdata(c);
	
	return apple6500_remove(m);
}

MODULE_DEVICE_TABLE(of, apple6500_dt_ids);

static struct i2c_driver apple6500_driver = {
	.driver = {
		.name	= APPLE6500_DRV_NAME,
		.of_match_table = apple6500_dt_ids,
	},
	.probe		= apple6500_i2c_probe,
	.remove   = apple6500_i2c_remove,
};

module_i2c_driver(apple6500_driver);

MODULE_AUTHOR("AppleCai");
MODULE_DESCRIPTION("APPLE6500 Acceler and Gyro Driver I2C");
MODULE_LICENSE("GPL");